package com.shujia.base.day02

/**
 * 面向对象编程
 * 核心的类型是类，主要的思路将对象在方法中传来传去
 * 方法的参数类型可以是一个类【抽象类，接口】，将来调用时可以传入一个对象在方法中，
 * 方法的返回值类型也可以是一个类【抽象类，接口】，将来调用完方法时得到一个对象。
 *
 *
 * 面向函数式编程
 * 本意就是将函数作为方法或函数的参数类型或返回值
 * 1、函数A是函数B的参数，调用函数B的时候，可以将函数A当作参数传入，可以在函数B的内部使用函数A
 * 2、函数A是函数B的返回值，调用完函数B的时候，可以得到一个函数A。
 *
 * 面向对象编程中，区分什么类型的对象，是由类的名字来区分并决定将来要传入什么对象或返回什么对象
 * 面向函数式编程中，怎么区分函数【或方法】的种类呢？
 * 答：函数是根据参数类型和返回值类型来区分的。
 *
 * 函数fun1：它的参数类型是一个字符串，返回值类型是一个Int类型
 * def show1(s:Student):Unit={
 * ...
 * }
 *
 * def show1(f:String=>Int):Unit={
 * ...
 * }
 *
 * 函数的数据类型：参数类型=>返回值类型
 *
 * 一、将函数作为另一个函数的参数类型传入
 */
object Demo13Function {
  def main(args: Array[String]): Unit = {
    def fun1(s: String): Int = {
      s.toInt + 100
    }
    //    println(fun1("1000"))

    //函数可以赋值给一个变量
    //    val a1:String=>Int = fun1
    //    println(a1("200"))

    //函数作为参数类型传入
    //    def show1(f:String=>Int):Unit={
    //      println(f("11"))
    //    }
    //    show1(fun1)

    //定义函数的时候，参数列表中，不仅有函数的类型，还有具体的值类型
    def show1(s: String, f: String => Int): Unit = {
      println(f(s))
    }

    //    def fun2(s:String):Int={
    //      s.toInt+111
    //    }
    //    def fun3(s:String):Int={
    //      s.toInt+222
    //    }
    //    def fun4(s:String):Int={
    //      s.toInt+333
    //    }
    //调用方式1：自己定义一个符合类型的函数传入
    //    show1("200", fun2)
    //    show1("200", fun3)
    //    show1("200", fun4)

    //调用方式2：直接在调用时使用lambda表达式
    show1("100", (s: String) => s.toInt + 111)
//    show1("100", (s: String) => s.toInt + 222)
//    show1("100", (s: String) => s.toInt + 333)

    //简化调用方式2写法1，数据类型可以不用写，scala语言会进行自动类型推断
    show1("100", s => s.toInt + 111)

    //简化调用方式2写法2，如果函数的参数只有一个的话，直接使用下划线代替左边的参数进行使用
    show1("100", _.toInt + 111)

  }
}
